package com.xlh.dokka.svc.service;

import com.xlh.dokka.api.DokkaImageService;
import com.xlh.dokka.svc.core.client.DockerClient;
import com.xlh.dokka.svc.core.client.Result;
import com.xlh.dokka.svc.core.model.Container;
import com.xlh.dokka.svc.core.model.Node;
import com.xlh.dokka.svc.dao.DokkaContainerMapper;
import com.xlh.dokka.svc.task.ImagePullListener;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;

/**
 * @author cheer
 */
@Service
@Slf4j
public class DokkaImageServiceImpl implements DokkaImageService {

    @Autowired
    private ThreadPoolTaskExecutor taskExecutor;

    @Autowired
    private DokkaContainerServiceImpl dokkaContainerService;

    @Autowired
    private DokkaContainerMapper dokkaContainerMapper;

    @Override
    public Boolean saveImage(Long dokkaId, String imageName) {
        if (dokkaId == null || StringUtils.isBlank(imageName)) {
            return false;
        }

        Container container = dokkaContainerMapper.getById(dokkaId);
        if (container == null) {
            return false;
        }

        if (DockerClient.commitImage(container.getHost(), container.getDockerId(), imageName) &&
                DockerClient.pushImage(container.getHost(), imageName)) {

            List<Node> nodes = dokkaContainerService.getNodes();
            if (CollectionUtils.isNotEmpty(nodes)) {
                CountDownLatch countDownLatch = new CountDownLatch(nodes.size());
                for (Node node : nodes) {
                    taskExecutor.submit(() -> {
                        if (DockerClient.pullImage(node.getIp(), imageName) != Result.NO_ERROR) {
                            ImagePullListener.putTask(node.getIp(), imageName);
                        }
                        countDownLatch.countDown();
                    });
                }
                try {
                    countDownLatch.await();
                } catch (InterruptedException e) {
                    log.warn("thread " + Thread.currentThread().getName() + " is interrupted");
                }
            }

            return true;
        }
        return false;
    }

    @Override
    @Async
    public void deleteImage(String imageName) {
        for (Node node : dokkaContainerService.getNodes()) {
            DockerClient.deleteImage(node.getIp(), imageName);
        }
    }

    @Override
    public List<String> inspectImage(String imageName) {
        List<String> hostList = new ArrayList<>();
        for (Node node : dokkaContainerService.getNodes()) {
            if (!DockerClient.inspectImage(node.getIp(), imageName)){
                hostList.add(node.getIp());
            }
        }
        return hostList;
    }

}
